#ifndef _LOG_H_
#define _LOG_H_
#include <stdarg.h>


#define store_cmp(x,y)	(strlen(x) > (sizeof(y)-1)? (sizeof(y)-1): strlen(x))


typedef int (*stream_out)(const char * format,...);

typedef int (*log_mutex_lock)(void * mutex);

typedef int (*log_mutex_unlock)(void * mutex);


typedef int (*get_clock)(int * year,int * month,int * day,int * hours,int * minute,int * second);

#define MAX_TAG_NAME_LENGTH			16
#define MAX_TAG_NUM					16

typedef struct {
	char tag_name[MAX_TAG_NAME_LENGTH];
	int  tag_output_filter;
} tag_info;

typedef struct {
	int info_log_len;
	int debug_log_len;
	int warn_log_len;
	int err_log_len;
} log_stat;

typedef struct {
	int global_output_filter;
	int global_display_filter;
	get_clock get_clock_callback;
	tag_info tag_conf[MAX_TAG_NUM];
	stream_out 	output_interface;
	log_mutex_lock log_lock;
	void * log_lock_para;
	log_mutex_unlock log_unlock;
	void * log_unlock_para;
}log_priv;



typedef enum {
	LOG_SYS_INFO 	= 0,
	LOG_SYS_DEBUG 	= 1,
	LOG_SYS_WARN 	= 2,
	LOG_SYS_ERROR 	= 3,
	LOG_SYS_NONE 	= 4
} LOG_LEVEL;



#define LOG_INFO_LEVEL		(1<<LOG_SYS_INFO)
#define LOG_DEBUG_LEVEL		(1<<LOG_SYS_DEBUG)
#define LOG_WARN_LEVEL		(1<<LOG_SYS_WARN)
#define LOG_ERROR_LEVEL		(1<<LOG_SYS_ERROR)
#define LOG_NONE_LEVEL		(1<<LOG_SYS_NONE)
#define LOG_ALL_LEVEL		(LOG_INFO_LEVEL|LOG_DEBUG_LEVEL|LOG_WARN_LEVEL|LOG_ERROR_LEVEL)


#define LOG_FILE_NAME_DISP_ENABLE	1<<0
#define LOG_FUNC_NAME_DISP_ENABLE	1<<1
#define LOG_LINE_NUM_DISP_ENABLE	1<<2
#define LOG_TIME_DISP_ENABLE		1<<3
#define LOG_DISP_OFF				1<<4
#define LOG_DISP_ALL	(LOG_FILE_NAME_DISP_ENABLE|LOG_FUNC_NAME_DISP_ENABLE|LOG_LINE_NUM_DISP_ENABLE|LOG_TIME_DISP_ENABLE)



#define LOG_TIME_STYLE " (%d-%d-%d %d:%d:%d) :"
#define LOG_LINE_NUM_NAME_STYLE " (%d) :"
#define LOG_FUNC_NAME_STYLE " %s :"
#define LOG_FILE_NAME_STYLE "%s :"
#define LOG_LEVEL_STYLE "%s/"
#define LOG_TAG_NAME_STYLE " (%s) :"





int log(const LOG_LEVEL log_level,const char * file_name,
const char * fun_name,const int line_num,
const char * name ,const char * format,...);

#define FILE_NAME_ENABLED
#define FUNC_NAME_ENABLED
#define LINE_NUM_ENABLED


#ifdef FILE_NAME_ENABLED
#define FILE_NAME __FILE__
#else
#define FILE_NAME 	""
#endif

#ifdef FUNC_NAME_ENABLED
#define FUNC_NAME __func__
#else
#define FUNC_NAME ""
#endif

#ifdef LINE_NUM_ENABLED
#define LINE_NUM  __LINE__
#else
#define LINE_NUM 0
#endif

void log_init(void);

int log_set_global_output_filter(const int log_level);

int log_set_tag_output_filter(const char * tag_name,const int log_level);

int log_register_output_stream( stream_out output_interface );

int log_set_Global_Display_filter(int global_display_filter );

int log_register_clock_callback(get_clock get_clock_callback);




#define logi(...) log(LOG_SYS_INFO,FILE_NAME,FUNC_NAME,LINE_NUM,LOG_TAG,__VA_ARGS__)
#define logd(...) log(LOG_SYS_DEBUG,FILE_NAME,FUNC_NAME,LINE_NUM,LOG_TAG,__VA_ARGS__)
#define logw(...) log(LOG_SYS_WARN,FILE_NAME,FUNC_NAME,LINE_NUM,LOG_TAG,__VA_ARGS__)
#define loge(...) log(LOG_SYS_ERROR,FILE_NAME,FUNC_NAME,LINE_NUM,LOG_TAG,__VA_ARGS__)


#endif
